#include "process.h"

void initProcesses()
{
	processes = malloc(MaxNumOfProcesses*sizeof(process_t));
	int i;
	//printf("malloc for processes size : %d\n", (MaxNumOfProcesses*sizeof(process_t)));

	for (i = 0; i < MaxNumOfProcesses; ++i)
	{
		processes[i].pid = -1;
	}
}

void killProcesses()
{
	if (isMonitorMode ) printf("processes was freed\n");
	FREE(processes);
	sem_destroy(&deamonSem);
	sem_destroy(&clockSem);
}

void processReadToFile(int vAddr, int pid,int amount, char* fileName){
	pthread_mutex_lock(&filesMutex);
	char* ans =readBytes(pid, vAddr, amount);
	ans[amount] = '\0';
	 if (isMonitorMode) printf("fileName: %s, pid : %d writing  : %s\n", fileName, pid, ans);
	FILE * f;
	f = fopen(fileName, "a");
	int i;
	for (i = 0; i < amount ; i++){
		fprintf(f, "%c",ans[i]);
	}
	fprintf(f, "\n");
	fclose(f);
	//FREE(f);
	FREE(ans)
	pthread_mutex_unlock(&filesMutex);
}

void processLoopReadToFile(int vAddr, int  pid, int off, int amount, char *fileName){
	int i;
	for (i = 0; i < amount; i++ ){
		processReadToFile(vAddr + (i * off),pid,1,fileName);
	}
}

void processReadByte(int pid, int vAddr, int amount){
	char* ans =readBytes(pid, vAddr, amount);
	int i;
	printf("read pid: %d\n", pid );
	for (i = 0; i < amount ; i++){
		printf("%c",ans[i]);
	}
	printf("\n");
	FREE(ans)
}

void processLoopRead(int vAddr, int  pid, int off, int amount){
	int i;
	for (i = 0; i < amount; i++ ){
		processReadByte(pid, vAddr + (i * off), 1);
	}
}

void processLoopWrite(int vAddr, int  pid, int off, int amount, char c){

	int i;
	for (i = 0; i < amount; i++ ){
		processWrite(vAddr + (i * off),pid,&c,1,1);
	}

}


/**
 * if isAtomic == 0, will not do the printing
 * else the function will print ok for success and errMsg for failure
 *  * */
void processWrite(int vAddr, int pid, char* s, int amount, int isAtomic){
	//sem_wait(&tempsem);
	int ans = writeBytes(pid, vAddr, amount, s );
	//sem_post(&tempsem);
	if (isAtomic){
		if (ans) printf("pid %d: write was ok\n", pid);
		else {
			printf("pid %d: the data you are trying to write is too big for the memory\n", pid);
		}
	}
}

//Gracefully deletes a process
void processDelete(int pid)
{
	processes[pid].pid = -1;
 	pcb[pid].isOccupied = 0;
 	sem_init(pcb[pid].waitForPRM,0, 1);
}

//TODO process exec function
void process_exec(int pid){
	int exit = 1;
	blockingQueue* mailbox = pcb[pid].mailbox;
	while (exit){
		pMessage_t * m = mbox_dequeue(mailbox);
		char* txt = m->messageText;
		if (strcmp("read",txt) == 0){
			processReadByte(pid, m->vAddr, m->byteAmmount);
		}
		else if(strcmp("exit",txt) == 0){
			exit = 0;
		}
		else if(strcmp("delProcess",txt) == 0){
			processDelete(pid);
			exit = 0;
		}
		else if(strcmp("loopRead",txt) == 0){
			processLoopRead(m->vAddr, pid, m->offset, m->byteAmmount);
		}
		else if(strcmp("write",txt) == 0){
			processWrite(m->vAddr, pid, m->stringParam, m->byteAmmount,1);
		}
		else if(strcmp("readToFile",txt) == 0){
			processReadToFile(m->vAddr, pid, m->byteAmmount, m->fileName);
		}
		else if(strcmp("loopWrite",txt) == 0){
			processLoopWrite(m->vAddr, pid, m->offset, m->byteAmmount, m->stringParam[0]);
		}
		else if(strcmp("loopReadToFile",txt) == 0){
			processLoopReadToFile(m->vAddr, pid, m->offset, m->byteAmmount, m->fileName);
		}
		killMessage(m);
	}
}

